﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace ChatTester
{
	class Program
	{
		private TcpClient clientsocket;
		private string serveraddress;
		private int clientsnum;
		private int messagesnum;
		private int channelsnum;
		private int serverport = 5555;

		private struct conStruct
        {
				internal NetworkStream ns;
				internal StreamReader sr;
        }
		private conStruct EstablishConnection()
		{
				conStruct cs = new conStruct();
				bool connected = false;
				clientsocket = new TcpClient(serveraddress,serverport);
				cs.ns = clientsocket.GetStream();
				cs.sr = new StreamReader(cs.ns);
				return cs;
		}
		struct testStruct
        {
            internal string clientname;
            internal int channelsnum;
            internal int messagesnum;
        }
		private void Test(object obj)
		{
            if (obj.GetType() != typeof(testStruct))
                return;
            testStruct ps = (testStruct)obj;
			Console.WriteLine(ps.clientname + " started the work");
            string message;
            Byte[] outbytes;
            conStruct cs = new conStruct();
			cs = EstablishConnection();
			Console.WriteLine(ps.clientname + "  established connection");
			message = "CONN|" + ps.clientname + "|";
			outbytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
			cs.ns.Write(outbytes,0,outbytes.Length);
			//System.Threading.Thread.Sleep(500);
			string[] tokens = cs.sr.ReadLine().Trim().Split(new Char[]{'|'});
			if(tokens[0] != "MOTD")
				return;
			Console.WriteLine(ps.clientname + "  registered");
			for(int i = 0; i < ps.channelsnum; i++)
			{
				message = "JOIN|test-channel" + i + "|"+ ps.clientname + "|\r\n";
				outbytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
				cs.ns.Write(outbytes,0,outbytes.Length);
				Console.WriteLine(ps.clientname + " joined test-channel" + i);
				for(int n = 0; n < ps.messagesnum; n++)
				{
					message = "CHAT|test-channel" + i + "|"+ ps.clientname + ": test message number "+ n + "|\r\n";
					outbytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
					cs.ns.Write(outbytes,0,outbytes.Length);
				}
			//System.Threading.Thread.Sleep(500);
				message = "LEAV|test-channel" + i + "|"+ ps.clientname + "|\r\n";
				outbytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
				cs.ns.Write(outbytes,0,outbytes.Length);
			Console.WriteLine(ps.clientname + " left test-channel" + i);
			}
			System.Threading.Thread.Sleep(500);
			message = "GONE|"+ ps.clientname + "|\r\n";
			outbytes = System.Text.Encoding.ASCII.GetBytes(message.ToCharArray());
			cs.ns.Write(outbytes,0,outbytes.Length);
			System.Threading.Thread.Sleep(500);
			cs.ns.Close();
			Console.WriteLine(ps.clientname + " finished task");
		}
		public static void Main(string[] args)
		{
       		ManualResetEvent resetEvent = new ManualResetEvent(false);
			Program ts = new Program();
			
			if(args.Length > 0)
				ts.serveraddress = args[0];
			else
				ts.serveraddress = "localhost";
			if(args.Length > 1)
				ts.clientsnum =  Convert.ToInt32(args[1]);
			else
				ts.clientsnum = 10;
			if(args.Length > 2)
				ts.messagesnum =  Convert.ToInt32(args[2]);
			else
				ts.messagesnum = 2;
			if(args.Length > 3)
				ts.channelsnum =  Convert.ToInt32(args[3]);
			else
				ts.channelsnum = 2;
        	int toProcess = ts.clientsnum;

			
			for(int i = 0; i < ts.clientsnum; i++)
			{
				testStruct ps = new testStruct();
				ps.clientname = "test-user"+i;
				ps.channelsnum = ts.channelsnum;
				ps.messagesnum = ts.messagesnum;
				
            new Thread(delegate()
            {
                Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                ts.Test(ps);
                // If we're the last thread, signal
                if (Interlocked.Decrement(ref toProcess) == 0)
                    resetEvent.Set();
            }).Start();
				//Thread oThread = new Thread(ts.Test);
				//oThread.Start(ps);
			}
        	resetEvent.WaitOne();
        	
			Console.Write("Press any key to continue . . . ");
			Console.ReadKey(true);
		}
	}
}